/**
 * @license
 * Copyright 2021 Du Tian Wei
 * SPDX-License-Identifier: Apache-2.0
 */

 const { contextBridge, ipcRenderer } = require('electron');
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const os = require('os');
const child_process = require('child_process');
const platform = os.platform();

process.traceProcessWarnings = true;
let runningViewer = null;
let root;
root = ipcRenderer.sendSync("appPath");
let appPath = ipcRenderer.sendSync('userData');
console.log(root);
console.log(appPath);
function _path(apath) {
    if (path.isAbsolute(apath)) {
        return apath;
    } else {
        return path.join(root, apath);
    }
}
let NativeInterface = {
    appPath,
    listFilesInDir(dirpath, opt, callback) {
        dirpath = _path(dirpath);
        let files = [];
        fs.opendir(dirpath, (err, dir) => {
            if (err) {
                callback(err);
                return;
            }
            function onEntry(dirent) {
                if (!dirent) {
                    dir.close();
                    callback(null, files);
                    return;
                }
                if (opt && opt.postfix) {
                    let match = false;
                    for (let i = 0; i < opt.postfix.length; i++) {
                        let postfix = opt.postfix[i];
                        if (dirent.name.endsWith(postfix)) {
                            match = true;
                            break;
                        }
                    }
                    if (!match) {
                        dir.read().then(onEntry);
                        return;
                    }
                }
                let fullpath = path.join(dirpath, dirent.name);
                files.push(fullpath);
                dir.read().then(onEntry);
            }
            dir.read().then(onEntry);
        });
    },
    readBinFilesInDir(dirpath, opt, callback) {
        dirpath = _path(dirpath);
        let errs = [];
        let bins = [];
        function readContent(_errs, files) {
            if (_errs) {
                callback(_errs);
                return;
            }
            if (files.length === 0) {
                callback(errs.length > 0 ? errs : null, bins);
            }
            files.forEach(file => {
                NativeInterface.readBinFile(file, (err, bin) => {
                    if (err) {
                        errs.push(err);
                    } else if (bin) {
                        bins.push(bin);
                    }
                    if (errs.length + bins.length === files.length) {
                        callback(errs.length > 0 ? errs : null, bins);
                    }
                });
            });
        }
        NativeInterface.listFilesInDir(dirpath, opt, readContent);
    },
    readTextFilesInDir(dirpath, opt, callback) {
        dirpath = _path(dirpath);
        let errs = [];
        let txts = [];
        function readContent(_errs, files) {
            if (_errs) {
                callback([_errs]);
                return;
            }
            if (files.length === 0) {
                callback(errs.length > 0 ? errs : null, txts);
            }
            files.forEach(file => {
                NativeInterface.readTextFile(file, (err, txt) => {
                    if (err) {
                        errs.push(err);
                    } else if (txt) {
                        txts.push(txt);
                    }
                    if (errs.length + txts.length === files.length) {
                        callback(errs.length > 0 ? errs : null, txts);
                    }
                });
            });
        }
        NativeInterface.listFilesInDir(dirpath, opt, readContent);
    },
    // opendir(...arg) {
    //     fs.opendir(...arg);
    // },
    copy(spath, tpath, ...args) {
        spath = _path(spath);
        tpath = _path(tpath);
        fse.copy(spath, tpath, ...args);
    },
    ensureFile(fpath, callback) {
        fpath = _path(fpath);
        let apath = path.resolve(fpath);
        return fse.ensureFile(apath, callback);
    },
    ensureDir(fpath, callback) {
        fpath = _path(fpath);
        let apath = path.resolve(fpath);
        return fse.ensureDir(apath, callback);
    },
    pathExists(fpath, callback) {
        fpath = _path(fpath);
        let apath = path.resolve(fpath);
        fse.pathExists(apath, callback);
    },
    writeTextFile(path, string, callback) {
        path = _path(path);
        fs.writeFile(path, string, callback);
    },
    writeBinFile(f, ...arg) {
        f = _path(f);
        fs.writeFile(f,...arg);
    },
    readTextFile(path, callback) {
        path = _path(path);
        fs.readFile(path, { encoding: 'utf-8' }, callback)
    },
    readBinFile(f, ...arg) {
        f = _path(f);
        fs.readFile(f,...arg)
    },
    removeFile(f,...arg) {
        f = _path(f);
        fs.unlink(f,...arg);
    },
    showOpenDialog(opt, callback) {
        let promise = ipcRenderer.invoke('dialog', 'showOpenDialog', opt);
        promise.then(callback);
    },
    openProject(p) {
        ipcRenderer.invoke('server', 'setProjectInfo', p)
    },
    runProject(p) {
        if (runningViewer && runningViewer.connected) {
            if (!runningViewer.kill('SIGHUP')) {
                console.log("not killed");
            }
        }
        let prefix = '';
        let postfix = '';
        switch (platform) {
            case 'darwin':
                prefix = 'open "';
                postfix = '.app"';
                break;
            case 'win32':
                prefix = '"';
                postfix = '/Viewer.exe"';
                break;
        }
        let path = `${prefix}${p.path}/bin/${platform}/Viewer${postfix}`;
        console.log(path);
        runningViewer = child_process.exec(path, (error, stdout, stderr) => {
            if (error) {
                throw error;
            }
            console.log(stdout);
            console.error(stderr);
        });
    }
};

contextBridge.exposeInMainWorld('NativeInterface', NativeInterface);